﻿//  Copyright (c) 2009 Ray Liang (http://www.dotnetage.com)
//  Dual licensed under the MIT and GPL licenses:
//  http://www.opensource.org/licenses/mit-license.php
//  http://www.gnu.org/licenses/gpl.html

using System;
using System.Web;
using System.Web.Mvc;
using System.IO;
using Microsoft.Practices.Unity;

namespace DNA.Mvc.Controllers
{
    /// <summary>
    ///  Extends Action that allows the View contains Widget, role base accessibility control,SEO meta editing feature.
    /// </summary>
    /// <remarks>
    /// When the administrator request that Url to Action that defines SiteMapActionAttribute and the Page is not exists in database,
    /// DotNetAge will auto create the web page instance for the request url.
    /// </remarks>
    public class SiteMapActionAttribute : ActionFilterAttribute
    {
        private bool showInMenu = true;
        private bool isShared = true;
        private string[] ignoreRouteValues;

        /// <summary>
        /// 
        /// </summary>
        public string[] IgnoreRouteDataKeys
        {
            get { return ignoreRouteValues; }
            set { ignoreRouteValues = value; }
        }

        /// <summary>
        /// Gets/Sets only create page for this action once time.
        /// </summary>
        /// <remarks>
        /// If this property sets the ExcludeValues will be enable
        /// </remarks>
        public bool IsShared
        {
            get { return isShared; }
            set { isShared = value; }
        }

        /// <summary>
        /// Gets/Sets the whether the SiteMapAction can shows in the main menu.
        /// </summary>
        public bool ShowInMenu
        {
            get { return showInMenu; }
            set { showInMenu = value; }
        }

        /// <summary>
        /// Gets/Sets the ParentAction name of the SiteMapAction
        /// </summary>
        public string ParentAction { get; set; }

        /// <summary>
        /// Gets/Sets the title of the SiteMapAction
        /// </summary>
        /// <remarks>
        /// This title will shows in menu and html header's title tag.
        /// </remarks>
        public string Title { get; set; }

        /// <summary>
        /// Gets/Sets the description of the SiteMapAction
        /// </summary>
        public string Description { get; set; }

        /// <summary>
        /// Gets/Sets the personal title when the page is a personal page.
        /// </summary>
        public string PersonalTitle { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public string PersonalDescription { get; set; }

        /// <summary>
        /// Gets/Sets the template file visual path that using when the action page is create.
        /// </summary>
        public string Template { get; set; }

        [Dependency]
        public WebSiteContext Context { get; set; }

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            //if (WebHost.IsInstalled)
            //{
            if (filterContext.HttpContext.Request.IsAuthenticated)
            {
                //var context = WebContext.Current;
                if (Context.Web != null)
                {
                    if (!Context.HasWebPage)
                    {
                        if (filterContext.RouteData.Values["controller"].ToString().Equals("DynamicUI", StringComparison.OrdinalIgnoreCase) &&
                            filterContext.RouteData.Values["action"].ToString().Equals("Index", StringComparison.OrdinalIgnoreCase))
                            return;

                        if ((IsShared) && (IgnoreRouteDataKeys != null) && (IgnoreRouteDataKeys.Length > 0))
                        {
                            if (Context.IsDefaultPageExists(IgnoreRouteDataKeys))
                                return;
                        }
                        bool isPersonalPage = false;

                        if (filterContext.RouteData.Values.ContainsKey("website"))
                            isPersonalPage = (!string.IsNullOrEmpty((filterContext.RouteData.Values["website"] as string)) &&
                                (!(filterContext.RouteData.Values["website"] as string).Equals("home", StringComparison.OrdinalIgnoreCase)));

                        var _path = Context.GetRouteDefaultUrl(IgnoreRouteDataKeys,filterContext.RouteData);
                        if (!string.IsNullOrEmpty(_path))
                        {
                            if (Context.User.IsAdministrator() || Context.User.IsWebOwner())
                            {
                                var page = Context.DataContext.WebPages.Create(
                                 new WebPage()
                                 {
                                     Path = _path,
                                     IsStatic = true,
                                     IsShared = IsShared,
                                     ViewData = ((IgnoreRouteDataKeys != null) && (IgnoreRouteDataKeys.Length > 0)) ? String.Join(",", IgnoreRouteDataKeys) : "",
                                     Title = isPersonalPage ? (string.IsNullOrEmpty(PersonalTitle) ? ((string.IsNullOrEmpty(Title) ? filterContext.ActionDescriptor.ActionName : Title)) : PersonalTitle) :
                                     (string.IsNullOrEmpty(Title) ? filterContext.ActionDescriptor.ActionName : Title),
                                     Description = isPersonalPage ? PersonalDescription : Description,
                                     ShowInMenu = ShowInMenu,
                                     Web = Context.Web,
                                     Owner = Context.Web.Owner,
                                     AllowAnonymous =(!filterContext.ActionDescriptor.IsDefined(typeof(AuthorizeAttribute),true) && !filterContext.ActionDescriptor.IsDefined(typeof(SecurityActionAttribute),true) && !filterContext.ActionDescriptor.IsDefined(typeof(PersonalOnlyAttribute),true))
                                 });
                                
                                if (!page.AllowAnonymous)
                                {
                                    var role = new WebPageRole() { 
                                        RoleName="administrators" ,
                                        WebPage =page
                                    };
                                    Context.DataContext.WebPageRoles.Create(role);
                                }
                                Context.DataContext.SaveChanges();
                                Context.Page = page;
                            }

                            //if (!string.IsNullOrEmpty(this.Template))
                            //{
                            //    var templateFile = HttpContext.Current.Server.MapPath(this.Template);
                            //    if (File.Exists(templateFile))
                            //    {
                            //        try
                            //        {
                            //            //string src = File.ReadAllText(templateFile);
                            //            ////var data = (new JavaScriptSerializer()).Deserialize<WebPageDataContract>(src);
                            //            ////page.Import(data);
                            //            //page.Import(src);
                            //        }
                            //        catch { }
                            //    }
                            //}
                        }
                    }
                }
            }
            //}
            base.OnActionExecuting(filterContext);
        }

    }
}
